package com.zbkj.crmeb.store.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import cn.hutool.core.util.BooleanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.crmeb.core.exception.CrmebException;
import com.taobao.pac.sdk.cp.dataobject.request.MODUAN_ORDER_CREATE.request;
import com.zbkj.crmeb.chant.model.ChannelMerchant;
import com.zbkj.crmeb.chant.model.ChannelMerchantDistribution;
import com.zbkj.crmeb.chant.service.ChannelMerchantDistributionService;
import com.zbkj.crmeb.chant.service.IChannelMerchantService;
import com.zbkj.crmeb.enums.*;
import com.zbkj.crmeb.finance.model.UserExtract;
import com.zbkj.crmeb.finance.service.UserExtractService;
import com.zbkj.crmeb.front.response.ProductDetailResponse;
import com.zbkj.crmeb.front.response.ProductResponse;
import com.zbkj.crmeb.front.service.ProductService;
import com.zbkj.crmeb.merchant.admin.service.MerStoreProductService;
import com.zbkj.crmeb.merchant.admin.service.StoreProductStockService;
import com.zbkj.crmeb.store.model.*;
import com.zbkj.crmeb.store.request.RetailShopStairUserRequest;
import com.zbkj.crmeb.store.response.*;
import com.zbkj.crmeb.store.service.*;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.CommonPage;
import com.common.PageParamRequest;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zbkj.crmeb.merchant.admin.service.MerRetailShopService;
import com.zbkj.crmeb.store.dao.UserCommissionDao;
import com.zbkj.crmeb.store.request.UserCommissionRequest;
import com.zbkj.crmeb.user.model.User;
import com.zbkj.crmeb.user.service.UserService;

/**
* @author Mr.Zhang
* @Description UserCommissionServiceImpl 接口实现
* @since 2020-05-28
*/
@Service
@Slf4j
public class UserCommissionServiceImpl extends ServiceImpl<UserCommissionDao, UserCommission> implements UserCommissionService {

    private static Logger logger = LoggerFactory.getLogger(UserCommissionServiceImpl.class);

    @Resource
    private  UserCommissionDao dao;

    @Autowired
    private StoreProductStockService storeProductStockService;
    @Autowired
    private UserService userService;
    @Autowired
    private MerRetailShopService retailShopService;
    @Autowired
    private IChannelMerchantService channelMerchantService;
    @Autowired
    private ChannelGroupBookingService channelGroupBookingService;
    @Autowired
    private StoreProductGroupActivityService storeProductGroupActivityService;
    @Autowired
    private StoreProductAttrValueService storeProductAttrValueService;
    @Autowired
    private ChannelMerchantDistributionService channelMerchantDistributionService;
    @Autowired
    private StoreOrderInfoService orderInfoService;
    @Autowired
    private UserExtractService userExtractService;
    @Autowired
    private MerStoreProductService merStoreProductService;
    @Autowired
    private StoreOrderService storeOrderService;
    @Autowired
    private StoreOrderInfoService storeOrderInfoService;
    @Autowired
    private ProductService productService;

    @Override
    public void freezeUserCommission(StoreOrder storeOrder,List<StoreOrderInfo> storeOrderInfoList,boolean leaderResult) {
        ChannelMerchantDistribution distribution = channelMerchantDistributionService.getOne(Wrappers.<ChannelMerchantDistribution>lambdaQuery().eq(ChannelMerchantDistribution::getMerId, storeOrder.getMerId()));
        //当前下单用户的信息
        User user = userService.getById(storeOrder.getUid());
        boolean flag = Objects.nonNull(distribution) && user.getSpreadUid() != null && user.getSpreadUid()>0;
        log.info("是否新增佣金流水,订单:{},{},{}", storeOrder.getId(), flag,leaderResult);
        if(!flag){
            return;
        }
        Integer activityGroupId = storeOrder.getActivityId();
        ChannelGroupBooking channelGroupBooking = channelGroupBookingService.getById(activityGroupId);
        Integer leaderId = null;
        // 团长id
        if(null != channelGroupBooking && null != channelGroupBooking.getLeaderId() && channelGroupBooking.getLeaderId() != 0) {
            leaderId = channelGroupBooking.getLeaderId();
        }

                // todo
        //一级
        Integer firstSpreadUid = user.getSpreadUid();
        BigDecimal oneRebateRate = distribution.getOneRebateRate();
        BigDecimal firstAmount = BigDecimal.ZERO;
        //二级
        User firstUser = userService.getById(firstSpreadUid);
        Integer secondSpreadUid = null;
        BigDecimal secondAmount = BigDecimal.ZERO;
        User secondUser = new User();
        if(firstUser.getSpreadUid() > 0){
            secondSpreadUid = firstUser.getSpreadUid();
            secondUser = userService.getById(secondSpreadUid);
        }
        ChannelMerchant channelMerchant = channelMerchantService.getById(storeOrder.getMerId());
        //一级分销员开启才能正常分佣,一级分销员关闭后二级分销员也无法分佣
        if (BooleanUtil.isTrue(firstUser.getDistributorFlag())){
            for (StoreOrderInfo storeOrderInfo : storeOrderInfoList) {
                StoreCartResponse storeCartResponse = JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class);
                StoreProductAttrValue attrInfo = storeCartResponse.getProductInfo().getAttrInfo();
                BigDecimal price = channelMerchant.getAppletType() == 1 ? attrInfo.getPaidPrice() : attrInfo.getProductPaidPrice();
                log.info("是否计算拼团佣金，是否是团长，是否能分销提成：{}，{}，{}", leaderResult, leaderId, firstSpreadUid);

                if(leaderResult && null != leaderId && leaderId.equals(firstSpreadUid)) {
                    log.info("一级分销员是团长，不能分销提成：{}，{}", leaderId, firstSpreadUid);
                }else {
                    log.info("可以计算分销提成：");
                    BigDecimal amount = price.multiply(oneRebateRate.movePointLeft(2)).setScale(2, RoundingMode.HALF_DOWN);
                    firstAmount = firstAmount.add(amount);
                    this.saveUserCommission(firstSpreadUid, storeOrderInfo.getChildOrderNumber(),
                            CommissionTypeEnum.YJ_佣金.getCode(), CommissionStatusEnum.YJDJ_佣金冻结.getCode(), CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                            amount, amount, null, null, null,
                            "购买商品-一级佣金", null);
                }
                //分销员开启才能正常分佣
                if(secondSpreadUid != null){
                    if (BooleanUtil.isTrue(secondUser.getDistributorFlag())){
                        log.info("是否计算拼团佣金，是否是团长，是否能分销提成：{}，{}，{}", leaderResult, leaderId, secondSpreadUid);
                        if(leaderResult && null != leaderId && leaderId.equals(secondSpreadUid)) {
                            log.info("二级分销员是团长，不能分销提成：{}，{}", leaderId, secondSpreadUid);
                        }else {
                            log.info("可以计算分销提成：");
                            BigDecimal secondCommission = price.multiply(distribution.getTwoRebateRate().movePointLeft(2)).setScale(2, RoundingMode.HALF_DOWN);
                            secondAmount = secondAmount.add(secondCommission);
                            this.saveUserCommission(secondSpreadUid, storeOrderInfo.getChildOrderNumber(),
                                    CommissionTypeEnum.YJ_佣金.getCode(), CommissionStatusEnum.YJDJ_佣金冻结.getCode(), CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                                    secondCommission, secondCommission, null, null, null,
                                    "购买商品-二级佣金", null);
                        }
                    }else {
                        log.info("用户上上级分销员被禁用无法分佣,订单:{}", storeOrder.getId());
                    }

                }
            }
            //用户资金处理
            User firstUserAccount = new User();
            firstUserAccount.setUid(firstSpreadUid);
            firstUserAccount.setBrokeragePrice(firstAmount);
            firstUserAccount.setFrozenPrice(firstAmount);
            if(BigDecimal.ZERO.compareTo(firstAmount) != 0) {
                userService.calcMoney(firstUserAccount);
            }
            if(secondSpreadUid != null && BooleanUtil.isTrue(secondUser.getDistributorFlag())){
                User secondUserAccount = new User();
                secondUserAccount.setUid(secondSpreadUid);
                secondUserAccount.setBrokeragePrice(secondAmount);
                secondUserAccount.setFrozenPrice(secondAmount);
                if(BigDecimal.ZERO.compareTo(secondAmount) != 0) {
                    userService.calcMoney(secondUserAccount);
                }
            }
        }else {
            log.info("用户上级分销员被禁用无法分佣,订单:{}", storeOrder.getId());
        }

    }

    /**
     * 判断是否是拼团商品:
     * 否：return
     * 是：检查拼团活动下的商品库存量
     *    大于0：按照优先级计算佣金：商品维度 > 商户分销模式表
     *    等于0：对历史订单重新计算佣金：
     *             先将该活动对应的订单下的活动商品id对应的佣金，全部取消(按照退款方式取消佣金)
     *             按照拼团佣金比例计算佣金
     *          对当前订单按照拼团佣金比例计算佣金
     *    对用户资金进行调整
     *
     *
     * @param storeOrder
     * @param storeOrderInfoList
     */
    @Override
    public boolean freezeUserCommissionV2(StoreOrder storeOrder,List<StoreOrderInfo> storeOrderInfoList) {

        // 判断是否是拼团商品
        String logID = UUID.randomUUID().toString();
        log.info("logID:[{}]", logID);
        log.info("freezeUserCommissionV2入口:[{}],{},{}",logID,JSONObject.toJSONString(storeOrder),JSONObject.toJSONString(storeOrderInfoList));
        if(null == storeOrder.getActivityId() || 0 == storeOrder.getActivityId()) {
            return false;
        }
        ChannelMerchantDistribution distribution = channelMerchantDistributionService.getOne(Wrappers.<ChannelMerchantDistribution>lambdaQuery().eq(ChannelMerchantDistribution::getMerId, storeOrder.getMerId()));
        ChannelMerchant channelMerchant = channelMerchantService.getById(storeOrder.getMerId());
        /* 1 拼团返佣比例 */
        Integer activityGroupId = storeOrder.getActivityId();
        ChannelGroupBooking channelGroupBooking = channelGroupBookingService.getById(activityGroupId);
        log.info("freezeUserCommissionV2拼团:[{}],{},{},{}",logID,JSONObject.toJSONString(distribution),JSONObject.toJSONString(channelMerchant),JSONObject.toJSONString(channelGroupBooking));
        // 团长id
        if(null == channelGroupBooking || null == channelGroupBooking.getLeaderId() || channelGroupBooking.getLeaderId() == 0) {
            return false;
        }
        Integer leaderId = channelGroupBooking.getLeaderId();
        // 团长佣金
        BigDecimal totalLeaderAmount = BigDecimal.ZERO;

        // 拼团活动商品
        List<StoreProductGroupActivity> activityList = storeProductGroupActivityService.list(Wrappers.<StoreProductGroupActivity>lambdaQuery()
                .eq(StoreProductGroupActivity::getActivityId, activityGroupId));
        // 获取商品id
        List<Integer> productIdList = activityList.stream().map(StoreProductGroupActivity::getProductId).distinct().collect(Collectors.toList());


//            Map<String, StoreProductGroupActivity> productGroupActivityMap = activityList.stream().collect(Collectors.toMap(StoreProductGroupActivity::getSourceSkuId, Function.identity(),(old, newData)->newData));

        // 获取拼团佣金比例
        BigDecimal activityRebateRate = channelGroupBooking.getRebateRate();
        Integer activityTimeType = channelGroupBooking.getActivityTimeType();
        if(activityRebateRate == null || activityRebateRate.compareTo(BigDecimal.ZERO) <= 0){
            // 这里也返回true吧，虽然佣金比例为0，但是是参与拼团的商品，就不允许计算分销佣金
            return true;
        }
        if(channelGroupBooking.getUseBaseRebateRate() != null && channelGroupBooking.getUseBaseRebateRate() == 0){
            // 不使用兜底佣金,只使用拼团佣金计算
            try {
                log.error("不使用兜底佣金,只使用拼团佣金计算");
                calculateUserCommissionWithRebateRate(logID, channelMerchant, channelGroupBooking, storeOrder, storeOrderInfoList);
                return true;
            }catch (Exception e){
                log.error("不使用兜底佣金,只使用拼团佣金计算-失败，", e);
            }
        }

        String groupId = storeProductGroupActivityService.getGroupIdByActivityId(activityGroupId);
        List<Integer> activityIds = storeProductGroupActivityService.getActivityIdsByGroupId(groupId);

        /** 判断这些商品的库存量是否都为0 */
        Integer stock = 0;
        // 商品规格
        List<StoreProductAttrValue> attrValueList = storeProductAttrValueService.list(Wrappers.<StoreProductAttrValue>lambdaQuery()
                .in(StoreProductAttrValue::getProductId, productIdList)
        );
        // 商品总库存量
        for(StoreProductAttrValue value : attrValueList){
            if(null != value.getStock() && value.getStock() >= 0){
                stock += value.getStock();
            }
            if(null != value.getGroupStock() && value.getGroupStock() >= 0){
                stock += value.getGroupStock();
            }
        }
        // 待支付库存量
        Integer unpaidStock = productService.getStockCountUnpaid(productIdList, activityIds);
        // 商品库存量 + 待支付库存量
        stock += unpaidStock;
        // 拼团锁定库存量
        log.info("freezeUserCommissionV2 拼团锁定库存量:[{}],{}",logID,groupId);

        Integer groupStock = 0;
        List<StoreProductGroupActivity> groupActivityList = new ArrayList<>();
        if(StringUtils.isNotBlank(groupId)){
            groupActivityList = storeProductGroupActivityService.list(Wrappers.<StoreProductGroupActivity>lambdaQuery()
                    .eq(StoreProductGroupActivity::getProductId, productIdList.get(0)) // 一个拼团只有一个productId,所以productIdList.get(0)
                    .eq(StoreProductGroupActivity::getGroupId, groupId));
            log.info("freezeUserCommissionV2 拼团锁定库存量11:[{}],{}",logID,JSON.toJSONString(groupActivityList));
        }else {
            List<ChannelGroupBooking> groupBookingList = channelGroupBookingService.list(Wrappers.<ChannelGroupBooking>lambdaQuery()
                    .eq(ChannelGroupBooking::getMerId, storeOrder.getMerId()));
            List<Integer> groupBookingIds = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(groupBookingList)){
                groupBookingIds =  groupBookingList.stream().map(ChannelGroupBooking::getId).collect(Collectors.toList());
            }
            groupActivityList = storeProductGroupActivityService.list(Wrappers.<StoreProductGroupActivity>lambdaQuery()
                    .eq(StoreProductGroupActivity::getProductId,  productIdList.get(0))
                    .in(StoreProductGroupActivity::getActivityId, groupBookingIds)
                    .isNull(StoreProductGroupActivity::getGroupId));
            log.info("freezeUserCommissionV2 拼团锁定库存量22:[{}],{}",logID,JSON.toJSONString(groupActivityList));

        }

        // 拼团库存量
        for(StoreProductGroupActivity value : groupActivityList){
            if(null != value.getStock() && value.getStock() >= 0){
                groupStock += value.getStock();
            }
        }
        // 拼团库存量 + 待支付库存量
        groupStock += unpaidStock;
        log.info("freezeUserCommissionV2 拼团库存量 + 待支付库存量:[{}],{}",logID,groupStock);

        // 是否卖完
        boolean isSoldOut = false;
        if(groupStock <= 0 || stock <= 0){
            isSoldOut = true;
        }

        log.info("freezeUserCommissionV2拼团活动商品:[{}],{},{},{}",logID,JSONObject.toJSONString(activityList),JSONObject.toJSONString(attrValueList),stock);
        log.info("freezeUserCommissionV2是否卖完:[{}],{}",logID,isSoldOut);

        // flag 是否已计算当前订单
        boolean flag = false;
        if(isSoldOut && activityTimeType == 1 && activityRebateRate != null && activityRebateRate.compareTo(BigDecimal.ZERO) > 0){
            flag = true;
            /** 重新计算佣金 */
            BigDecimal leaderAmount = recalculateUserCommission(logID,channelMerchant, activityGroupId, activityRebateRate, leaderId);
            totalLeaderAmount = totalLeaderAmount.add(leaderAmount);

        }
        // 然后对 storeOrderInfoList 进行循环，对于拼团商品对应的拼团库存量，是否为0，为0的话就重新计算佣金
        // 对当前订单计算佣金\
        if(!flag) {
            for (StoreOrderInfo storeOrderInfo : storeOrderInfoList) {
                StoreCartResponse storeCartResponse = JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class);
                StoreProductAttrValue attrInfo = storeCartResponse.getProductInfo().getAttrInfo();
                log.info("对当前订单循环计算佣金:[{}],{},{}", logID, JSONObject.toJSONString(storeCartResponse), JSONObject.toJSONString(attrInfo));

                // 对当前订单按照拼团佣金比例计算佣金
                if (isSoldOut && activityTimeType == 1 && activityRebateRate != null && activityRebateRate.compareTo(BigDecimal.ZERO) > 0) {
                    log.info("对当前订单按照拼团佣金比例计算佣金00:[{}]", logID);

                    // 对当前商品按照拼团佣金比例重新计算
                    BigDecimal price = channelMerchant.getAppletType() == 1 ? attrInfo.getPaidPrice() : attrInfo.getProductPaidPrice();
                    BigDecimal amount = price.multiply(activityRebateRate.movePointLeft(2)).setScale(2, RoundingMode.HALF_DOWN);
                    totalLeaderAmount = totalLeaderAmount.add(amount);
                    log.info("对当前订单按照拼团佣金比例计算佣金:[{}],{},{}", logID, amount, totalLeaderAmount);

                    this.saveUserCommissionV2(leaderId, storeOrderInfo.getChildOrderNumber(),
                            CommissionTypeEnum.YJ_佣金.getCode(), CommissionStatusEnum.YJDJ_佣金冻结.getCode(), CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                            amount, amount, null, null, null,
                            "购买商品-团长佣金", null, activityGroupId, 1, 0);
                } else {
                    log.info("按照优先级计算佣金00:[{}]", logID);

                    // 按照优先级计算佣金
                    // 获取商品的佣金比例
                    StoreProductMer storeProduct = merStoreProductService.getProductMerById(storeOrderInfo.getProductId(), storeOrder.getMerId());
                    BigDecimal rebateRate = storeProduct.getRebateRate();
                    if (null != rebateRate && rebateRate.compareTo(BigDecimal.ZERO) > 0) {
                        log.info("按照商品维度计算佣金00:[{}]", logID);

                        // 按照商品维度计算佣金
                        BigDecimal price = channelMerchant.getAppletType() == 1 ? attrInfo.getPaidPrice() : attrInfo.getProductPaidPrice();
                        BigDecimal amount = price.multiply(rebateRate.movePointLeft(2)).setScale(2, RoundingMode.HALF_DOWN);
                        totalLeaderAmount = totalLeaderAmount.add(amount);
                        log.info("按照商品维度计算佣金:[{}],{},{}", logID, amount, totalLeaderAmount);

                        this.saveUserCommissionV2(leaderId, storeOrderInfo.getChildOrderNumber(),
                                CommissionTypeEnum.YJ_佣金.getCode(), CommissionStatusEnum.YJDJ_佣金冻结.getCode(), CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                                amount, amount, null, null, null,
                                "购买商品-团长佣金", null, activityGroupId, 0, 0);
                    } else {
                        log.info("按照兜底返佣比例计算00:[{}]", logID);

                        // 按照兜底返佣比例计算
                        BigDecimal price = channelMerchant.getAppletType() == 1 ? attrInfo.getPaidPrice() : attrInfo.getProductPaidPrice();
                        BigDecimal baseRebateRate = distribution.getBaseRebateRate();
                        if (null != baseRebateRate && baseRebateRate.compareTo(BigDecimal.ZERO) > 0) {
                            BigDecimal amount = price.multiply(baseRebateRate.movePointLeft(2)).setScale(2, RoundingMode.HALF_DOWN);
                            totalLeaderAmount = totalLeaderAmount.add(amount);
                            log.info("按照兜底返佣比例计算:[{}],{},{}", logID, amount, totalLeaderAmount);
                            this.saveUserCommissionV2(leaderId, storeOrderInfo.getChildOrderNumber(),
                                    CommissionTypeEnum.YJ_佣金.getCode(), CommissionStatusEnum.YJDJ_佣金冻结.getCode(), CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                                    amount, amount, null, null, null,
                                    "购买商品-团长佣金", null, activityGroupId, 0, 0);

                        }
                    }


                }

            }
        }
        //用户资金处理
        User userAccount = new User();
        userAccount.setUid(leaderId);
        userAccount.setBrokeragePrice(totalLeaderAmount);
        userAccount.setFrozenPrice(totalLeaderAmount);
        log.info("用户资金处理totalLeaderAmount:{}", totalLeaderAmount);

        if(BigDecimal.ZERO.compareTo(totalLeaderAmount) != 0) {
            userService.calcMoney(userAccount);
        }
        return true;
    }
    /**
     * 不使用兜底佣金,只使用拼团佣金计算
     * @param logID
     * @param channelMerchant
     */
    private boolean calculateUserCommissionWithRebateRate(String logID, ChannelMerchant channelMerchant, ChannelGroupBooking channelGroupBooking, StoreOrder storeOrder,List<StoreOrderInfo> storeOrderInfoList) {
        log.info("只使用拼团佣金：calculateUserCommissionWithRebateRate:[{}],{},{}",logID,JSONObject.toJSONString(channelMerchant),JSONObject.toJSONString(channelGroupBooking));
        /* 1 拼团返佣比例 */
        Integer activityGroupId = channelGroupBooking.getId();
        Integer leaderId = channelGroupBooking.getLeaderId();
        // 获取拼团佣金比例
        BigDecimal activityRebateRate = channelGroupBooking.getRebateRate();
//        Integer activityTimeType = channelGroupBooking.getActivityTimeType();

        // 团长佣金
        BigDecimal totalLeaderAmount = BigDecimal.ZERO;

        for (StoreOrderInfo storeOrderInfo : storeOrderInfoList) {
            StoreCartResponse storeCartResponse = JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class);
            StoreProductAttrValue attrInfo = storeCartResponse.getProductInfo().getAttrInfo();
            log.info("只使用拼团佣金：对当前订单循环计算佣金:[{}],{},{}", logID, JSONObject.toJSONString(storeCartResponse), JSONObject.toJSONString(attrInfo));

            // 对当前订单按照拼团佣金比例计算佣金
            if (activityRebateRate != null && activityRebateRate.compareTo(BigDecimal.ZERO) > 0) {
                log.info("只使用拼团佣金：对当前订单按照拼团佣金比例计算佣金:[{}]", logID);

                // 对当前商品按照拼团佣金比例重新计算
                BigDecimal price = channelMerchant.getAppletType() == 1 ? attrInfo.getPaidPrice() : attrInfo.getProductPaidPrice();
                BigDecimal amount = price.multiply(activityRebateRate.movePointLeft(2)).setScale(2, RoundingMode.HALF_DOWN);
                totalLeaderAmount = totalLeaderAmount.add(amount);
                log.info("只使用拼团佣金：对当前订单按照拼团佣金比例计算佣金:[{}],{},{}", logID, amount, totalLeaderAmount);

                this.saveUserCommissionV2(leaderId, storeOrderInfo.getChildOrderNumber(),
                        CommissionTypeEnum.YJ_佣金.getCode(), CommissionStatusEnum.YJDJ_佣金冻结.getCode(), CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                        amount, amount, null, null, null,
                        "购买商品-团长佣金", null, activityGroupId, 1, 0);
            }
        }

        //用户资金处理
        User userAccount = new User();
        userAccount.setUid(leaderId);
        userAccount.setBrokeragePrice(totalLeaderAmount);
        userAccount.setFrozenPrice(totalLeaderAmount);
        log.info("只使用拼团佣金：用户资金处理totalLeaderAmount:{}", totalLeaderAmount);

        if(BigDecimal.ZERO.compareTo(totalLeaderAmount) != 0) {
            userService.calcMoney(userAccount);
        }
        return true;
    }

    /**
     * 重新计算佣金
     * @return
     */
    private BigDecimal recalculateUserCommission(String logID, ChannelMerchant channelMerchant, Integer activityGroupId, BigDecimal rebateRate, Integer leaderId) {
        log.info("recalculateUserCommission:[{}],{},{},{},{}",logID,JSONObject.toJSONString(channelMerchant),activityGroupId,rebateRate,leaderId);

        BigDecimal leaderAmount = BigDecimal.ZERO;
        // 先将该活动对应的订单下的活动商品id对应的佣金，全部取消(按照退款方式取消佣金)，然后对其重新计算佣金
        List<StoreOrder> storeOrderList = storeOrderService.list(Wrappers.<StoreOrder>lambdaQuery()
                .eq(StoreOrder::getActivityId, activityGroupId));
        List<Integer> orderIds = storeOrderList.stream().map(StoreOrder::getId).distinct().collect(Collectors.toList());
        List<StoreOrderInfo> orderInfoList = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery()
                .in(StoreOrderInfo::getOrderId, orderIds));

        BigDecimal returnBrokerage = BigDecimal.ZERO;
        BigDecimal returnFrozen = BigDecimal.ZERO;
        log.info("recalculateUserCommission该活动对应的订单下的活动商品:[{}],{},{}",logID,JSONObject.toJSONString(storeOrderList),JSONObject.toJSONString(orderInfoList));

        for(StoreOrderInfo info : orderInfoList){
            List<UserCommission> commissionList = getFrozenUserCommissionsGroupActivity(info, activityGroupId);
            log.info("recalculateUserCommission getFrozenUserCommissionsGroupActivity:[{}],{}",logID,JSONObject.toJSONString(commissionList));
            for(UserCommission userCommission : commissionList){
                userCommission.setIsFreeze(CommissionFreezeEnum.NOFREEZE_不可解冻.getCode());
                dao.updateById(userCommission);
                //2、新增复制原资金记录 取消重算类型
                this.saveUserCommission(userCommission.getUid(), userCommission.getOrderId(),
                        CommissionTypeEnum.CS_取消重算.getCode(), CommissionStatusEnum.YJDJ_佣金冻结.getCode(), CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                        userCommission.getTotalAmount().negate(), userCommission.getFreezeAmount().negate(), null, null, null,
                        userCommission.getTitle() + "-取消重算", null);
                returnBrokerage = returnBrokerage.add(userCommission.getTotalAmount());
                returnFrozen = returnFrozen.add(userCommission.getFreezeAmount());
            }
            StoreCartResponse storeCartResponse3 = JSON.parseObject(info.getInfo(), StoreCartResponse.class);
            StoreProductAttrValue attrInfo3 = storeCartResponse3.getProductInfo().getAttrInfo();

            // 是否有佣金比例，有的话就继续计算（主要是为了退款的时候这里不要继续往下算了）
            if(null == rebateRate || rebateRate.compareTo(BigDecimal.ZERO) <= 0){
                continue;
            }
            // 对以前的商品按照拼团佣金比例重新计算
            BigDecimal price = channelMerchant.getAppletType() == 1 ? attrInfo3.getPaidPrice() : attrInfo3.getProductPaidPrice();
            BigDecimal amount = price.multiply(rebateRate.movePointLeft(2)).setScale(2, RoundingMode.HALF_DOWN);
            leaderAmount = leaderAmount.add(amount);
            Integer orderComplete = 0;
            if(null != info.getStatus() && OrderStatusEnum.COMPLETE.getCode() == info.getStatus()){
                orderComplete = 1;
            }
            this.saveUserCommissionV2(leaderId,info.getChildOrderNumber(),
                    CommissionTypeEnum.YJ_佣金.getCode(),CommissionStatusEnum.YJDJ_佣金冻结.getCode(),CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                    amount,amount,null,null,null,
                    "购买商品-团长佣金",null, activityGroupId, 1,orderComplete);
        }
        //用户资金操作
        log.info("recalculateUserCommission 用户资金操作:[{}],{},{}",logID,returnBrokerage, returnFrozen);
        User userAccount = new User();
        userAccount.setUid(leaderId);
        userAccount.setBrokeragePrice(returnBrokerage.negate());
        userAccount.setFrozenPrice(returnFrozen.negate());
        userService.calcMoney(userAccount);
        return leaderAmount;
    }

    @Override
    public void setPreferentialPrice(ProductDetailResponse productDetailResponse, ProductResponse productResponse, Integer uid, Integer merId) {
        ChannelMerchantDistribution distribution = channelMerchantDistributionService.getOne(Wrappers.<ChannelMerchantDistribution>lambdaQuery().eq(ChannelMerchantDistribution::getMerId, merId));
        //当前用户的信息
        if(uid == null){
            try {
                uid = userService.getUserIdException();
            }catch (Exception e){
                log.error("获取当前用户id错误：{}", e);
            }
        }
        User user = userService.getById(uid);
        boolean flag = Objects.nonNull(distribution) && user.getSpreadUid() != null && user.getSpreadUid()>0;
        log.info("当前用户是否有资格享有优惠价,用户名:{},{}", user.getNickname(), flag);


        if(flag){
            // 推广员
            Integer firstSpreadUid = user.getSpreadUid();
            // 推广员是否是分销员
            User firstUser = userService.getById(firstSpreadUid);
            //分销员开启才能给优惠价
            if (BooleanUtil.isTrue(firstUser.getDistributorFlag())){
                // TODO
                log.info("当前用户可以享有优惠价,用户名:{}", user.getNickname());
                if(null != productDetailResponse) {
                    productDetailResponse.setIsPreferential(SwitchEnum.OPEN.getCode());
                }
                if(null != productResponse) {
                    productResponse.setIsPreferential(SwitchEnum.OPEN.getCode());
                }
                return;
            }else {
                log.info("分销员的分销被禁用,分销员:{}", firstUser.getNickname());
            }

        }

        if(null != productDetailResponse) {
            List<StoreProductAttrValueResponse> productValues = productDetailResponse.getProductValues();
            for (StoreProductAttrValueResponse value : productValues) {
                value.setPrice(BigDecimal.ZERO);
//                value.setPromotePrice(BigDecimal.ZERO);
                value.setVipPrice(BigDecimal.ZERO);
                value.setV2Price(BigDecimal.ZERO);
                value.setV3Price(BigDecimal.ZERO);
                value.setOtPrice(BigDecimal.ZERO);
                value.setCost(BigDecimal.ZERO);
//                value.setSourceCost(BigDecimal.ZERO);
//                value.setRaisePrice(BigDecimal.ZERO);
                value.setFirstPrice(BigDecimal.ZERO);
                value.setTaxAndSecondPrice(BigDecimal.ZERO);
//                value.setTaxPrice(BigDecimal.ZERO);
                value.setSecondPrice(BigDecimal.ZERO);
//                value.setFirstAgentCost(BigDecimal.ZERO);
//                value.setSecondAgentCost(BigDecimal.ZERO);
                value.setMemberDiscountPrice(BigDecimal.ZERO);
                value.setSpikePrice(BigDecimal.ZERO);
//                value.setPackagePrice(BigDecimal.ZERO);
            }
            StoreProductStoreInfoResponse storeInfo = productDetailResponse.getStoreInfo();
            // TODO
            storeInfo.setPrice(BigDecimal.ZERO);
            storeInfo.setPostage(BigDecimal.ZERO);
            storeInfo.setVipPrice(BigDecimal.ZERO);
//            storeInfo.setV2Price(BigDecimal.ZERO);
//            storeInfo.setV3Price(BigDecimal.ZERO);
            storeInfo.setOtPrice(BigDecimal.ZERO);
            storeInfo.setCost(BigDecimal.ZERO);
//            storeInfo.setSourceCost(BigDecimal.ZERO);
//            storeInfo.setRaisePrice(BigDecimal.ZERO);
            storeInfo.setFirstPrice(BigDecimal.ZERO);
            storeInfo.setTaxAndSecondPrice(BigDecimal.ZERO);
//            storeInfo.setTaxPrice(BigDecimal.ZERO);
//            storeInfo.setSecondPrice(BigDecimal.ZERO);
//            storeInfo.setFirstAgentCost(BigDecimal.ZERO);
//            storeInfo.setSecondAgentCost(BigDecimal.ZERO);
            storeInfo.setMemberDiscountPrice(BigDecimal.ZERO);
            storeInfo.setSpikePrice(BigDecimal.ZERO);
//            storeInfo.setPackagePrice(BigDecimal.ZERO);
            // 不享有优惠专属价
            productDetailResponse.setIsPreferential(SwitchEnum.CLOSE.getCode());
        }

        if(null != productResponse) {

            // TODO
            productResponse.setPrice(BigDecimal.ZERO);
//            productResponse.setPromotePrice(BigDecimal.ZERO);
            productResponse.setVipPrice(BigDecimal.ZERO);
            productResponse.setV2Price(BigDecimal.ZERO);
            productResponse.setV3Price(BigDecimal.ZERO);
            productResponse.setOtPrice(BigDecimal.ZERO);
            productResponse.setOtPriceRmb(BigDecimal.ZERO);
//            productResponse.setSourceCost(BigDecimal.ZERO);
//            productResponse.setRaisePrice(BigDecimal.ZERO);
            productResponse.setFirstPrice(BigDecimal.ZERO);
            productResponse.setTaxAndSecondPrice(BigDecimal.ZERO);
            productResponse.setPackagePrice(BigDecimal.ZERO);
//            productResponse.setSecondPrice(BigDecimal.ZERO);
//            productResponse.setFirstAgentCost(BigDecimal.ZERO);
//            productResponse.setSecondAgentCost(BigDecimal.ZERO);
            productResponse.setMemberDiscountPrice(BigDecimal.ZERO);
            productResponse.setSpikePrice(BigDecimal.ZERO);
            productResponse.setPackagePrice(BigDecimal.ZERO);
            // 不享有优惠专属价
            productResponse.setIsPreferential(SwitchEnum.CLOSE.getCode());
        }

    }

    @Override
    public void freezeUserCommissionTest(StoreOrder storeOrder,List<StoreOrderInfo> storeOrderInfoList) {
        ChannelMerchantDistribution distribution = channelMerchantDistributionService.getOne(Wrappers.<ChannelMerchantDistribution>lambdaQuery().eq(ChannelMerchantDistribution::getMerId, storeOrder.getMerId()));
        //当前下单用户的信息
        User user = userService.getById(storeOrder.getUid());
        boolean flag = Objects.nonNull(distribution) && user.getSpreadUid() != null && user.getSpreadUid()>0;
        log.info("是否新增佣金流水,订单:{},{}", storeOrder.getId(), flag);
        if(!flag){
            return;
        }
        // todo
        //一级
        Integer firstSpreadUid = user.getSpreadUid();
        BigDecimal oneRebateRate = distribution.getOneRebateRate();

        //二级
        User firstUser = userService.getById(firstSpreadUid);
        Integer secondSpreadUid = null;

        User secondUser = new User();
        if(firstUser.getSpreadUid() > 0){
            secondSpreadUid = firstUser.getSpreadUid();
            secondUser = userService.getById(secondSpreadUid);
        }
        ChannelMerchant channelMerchant = channelMerchantService.getById(storeOrder.getMerId());
        //一级分销员开启才能正常分佣,一级分销员关闭后二级分销员也无法分佣
        if (BooleanUtil.isTrue(firstUser.getDistributorFlag())){
            for (StoreOrderInfo storeOrderInfo : storeOrderInfoList) {
                BigDecimal firstAmount = BigDecimal.ZERO;
                StoreCartResponse storeCartResponse = JSON.parseObject(storeOrderInfo.getInfo(), StoreCartResponse.class);
                StoreProductAttrValue attrInfo = storeCartResponse.getProductInfo().getAttrInfo();
                BigDecimal price = channelMerchant.getAppletType() == 1 ? attrInfo.getPaidPrice() : attrInfo.getProductPaidPrice();
                BigDecimal amount = price.multiply(oneRebateRate.movePointLeft(2)).setScale(2, RoundingMode.HALF_DOWN);
                firstAmount = firstAmount.add(amount);
                List<UserCommission> commissionList1 = this.getFrozenUserCommissionsTest(firstSpreadUid,storeOrderInfo.getChildOrderNumber());
                if(CollectionUtils.isEmpty(commissionList1)){
                    this.saveUserCommission(firstSpreadUid,storeOrderInfo.getChildOrderNumber(),
                            CommissionTypeEnum.YJ_佣金.getCode(),CommissionStatusEnum.YJDJ_佣金冻结.getCode(),CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                            amount,amount,null,null,null,
                            "购买商品-一级佣金",null);
                    //用户资金处理
                    User firstUserAccount = new User();
                    firstUserAccount.setUid(firstSpreadUid);
                    firstUserAccount.setBrokeragePrice(firstAmount);
                    firstUserAccount.setFrozenPrice(firstAmount);
                    if(BigDecimal.ZERO.compareTo(firstAmount) != 0) {
                        userService.calcMoney(firstUserAccount);
                    }

                    // 解冻
                    if(OrderStatusEnum.COMPLETE.getCode().equals(storeOrderInfo.getStatus())) {
                        completeCommissionTest(storeOrderInfo);
                    }
                }

                //分销员开启才能正常分佣
                if(secondSpreadUid != null){
                    if (BooleanUtil.isTrue(secondUser.getDistributorFlag())){
                        BigDecimal secondAmount = BigDecimal.ZERO;
                        BigDecimal secondCommission = price.multiply(distribution.getTwoRebateRate().movePointLeft(2)).setScale(2, RoundingMode.HALF_DOWN);
                        secondAmount = secondAmount.add(secondCommission);
                        List<UserCommission> commissionList2 = this.getFrozenUserCommissionsTest(secondSpreadUid,storeOrderInfo.getChildOrderNumber());
                        if(CollectionUtils.isEmpty(commissionList2)) {
                            this.saveUserCommission(secondSpreadUid, storeOrderInfo.getChildOrderNumber(),
                                    CommissionTypeEnum.YJ_佣金.getCode(), CommissionStatusEnum.YJDJ_佣金冻结.getCode(), CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                                    secondCommission, secondCommission, null, null, null,
                                    "购买商品-二级佣金", null);
                            User secondUserAccount = new User();
                            secondUserAccount.setUid(secondSpreadUid);
                            secondUserAccount.setBrokeragePrice(secondAmount);
                            secondUserAccount.setFrozenPrice(secondAmount);
                            if(BigDecimal.ZERO.compareTo(secondAmount) != 0) {
                                userService.calcMoney(secondUserAccount);
                            }
                            // 解冻
                            if(OrderStatusEnum.COMPLETE.getCode().equals(storeOrderInfo.getStatus())) {
                                completeCommissionTest(storeOrderInfo);
                            }
                        }
                    }else {
                        log.info("用户上上级分销员被禁用无法分佣,订单:{}", storeOrder.getId());
                    }

                }
            }

        }else {
            log.info("用户上级分销员被禁用无法分佣,订单:{}", storeOrder.getId());
        }

    }

    /**
     * 支付成功之后, 需要事物处理
     * @author Mr.Zhang
     * @since 2020-06-22
     * @return
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Error.class, CrmebException.class})
    public void userCommissionCancel(StoreOrderInfo orderInfo){
        //1、更新资金记录 订单号为退款订单号 冻结流水 状态为不可解冻
        List<UserCommission> list = getFrozenUserCommissionsV2(orderInfo);
        list.forEach(userCommission -> {
            userCommission.setIsFreeze(CommissionFreezeEnum.NOFREEZE_不可解冻.getCode());
            BigDecimal totalAmount = userCommission.getTotalAmount();
            BigDecimal freezeAmount = userCommission.getFreezeAmount();
            BigDecimal withdrawalAmount = userCommission.getWithdrawalAmount();

            if("购买商品-一级佣金".equals(userCommission.getTitle())) {

                //用户资金操作
                User userAccount = new User();
                userAccount.setUid(userCommission.getUid());
                userAccount.setBrokeragePrice(totalAmount.negate());
                userAccount.setFrozenPrice(freezeAmount.negate());
                userService.calcMoney(userAccount);

            }else if("购买商品-一级佣金-解冻".equals(userCommission.getTitle())){

                //用户资金操作
                User userAccount = new User();
                userAccount.setUid(userCommission.getUid());
                userAccount.setFrozenPrice(freezeAmount.negate());
                userAccount.setWithdrawalPrice(withdrawalAmount.negate());
                userService.calcMoney(userAccount);

            }else if("购买商品-一级佣金-退款".equals(userCommission.getTitle())){

                //用户资金操作
                User userAccount = new User();
                userAccount.setUid(userCommission.getUid());
                userAccount.setBrokeragePrice(totalAmount.negate());
                userAccount.setFrozenPrice(freezeAmount.negate());
                userService.calcMoney(userAccount);
            }
            userCommission.setTotalAmount(BigDecimal.ZERO);
            userCommission.setFreezeAmount(BigDecimal.ZERO);
            userCommission.setWithdrawalAmount(BigDecimal.ZERO);
            dao.updateById(userCommission);
        });

    }

    @Override
    public void refundCommission(StoreOrderInfo storeOrderInfo) {
        //1、更新资金记录 订单号为退款订单号 冻结流水 状态为不可解冻
        List<UserCommission> list = getFrozenUserCommissions(storeOrderInfo);
        list.forEach(userCommission -> {
            userCommission.setIsFreeze(CommissionFreezeEnum.NOFREEZE_不可解冻.getCode());
            dao.updateById(userCommission);
            //2、新增复制原资金记录 退款类型
            this.saveUserCommission(userCommission.getUid(), userCommission.getOrderId(),
                    CommissionTypeEnum.TK_退款.getCode(), CommissionStatusEnum.YJDJ_佣金冻结.getCode(), CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                    userCommission.getTotalAmount().negate(), userCommission.getFreezeAmount().negate(), null, null, null,
                    userCommission.getTitle() + "-退款", null);
            //用户资金操作
            User userAccount = new User();
            userAccount.setUid(userCommission.getUid());
            userAccount.setBrokeragePrice(userCommission.getTotalAmount().negate());
            userAccount.setFrozenPrice(userCommission.getFreezeAmount().negate());
            userService.calcMoney(userAccount);
        });

        try {
            // 对于拼团佣金需要重算
            refundCommissionGroupActivity(storeOrderInfo, list);
        }catch (Exception e){
            logger.error("拼团活动的团长佣金重算错误，{}", e);
        }


    }

    /**
     * 判断当前订单是否使用了拼团佣金比例
     * 否：return
     * 是：重新计算佣金
     *      先将该活动对应的订单下的活动商品id对应的佣金，全部取消
     *      对以前的订单按照佣金比例的优先级重新计算
     *         是否存在商品维度的佣金比例
     *            存在就按照商品维度的佣金比例计算
     *            不存在就按照渠道商维度的佣金比例计算
     *
     * @param orderInfo
     * @param commissionList
     */
    private void refundCommissionGroupActivity(StoreOrderInfo orderInfo, List<UserCommission> commissionList) {
        String logID = UUID.randomUUID().toString();
        log.info("logID:[{}]", logID);
        log.info("refundCommissionGroupActivity:[{}],{},{}",logID,JSONObject.toJSONString(orderInfo),JSONObject.toJSONString(commissionList));

        // 获取当前订单
        StoreOrder storeOrder = storeOrderService.getById(orderInfo.getOrderId());

        Integer activityGroupId = storeOrder.getActivityId();
        if(null == activityGroupId || 0 == activityGroupId){
            return;
        }
        List<UserCommission> list2 = commissionList.stream().filter(e -> activityGroupId == e.getActivityGroupId()).collect(Collectors.toList());
        UserCommission commission = list2.get(0);
        // 是否使用了拼团佣金比例
        if(commission.getIsGroupRebate() != 1){
            return;
        }

        ChannelMerchantDistribution distribution = channelMerchantDistributionService.getOne(Wrappers.<ChannelMerchantDistribution>lambdaQuery().eq(ChannelMerchantDistribution::getMerId, storeOrder.getMerId()));
        ChannelMerchant channelMerchant = channelMerchantService.getById(storeOrder.getMerId());
        ChannelGroupBooking channelGroupBooking = channelGroupBookingService.getById(activityGroupId);
        log.info("refundCommissionGroupActivity拼团佣金比例:[{}],{},{},{}",logID,JSONObject.toJSONString(distribution),JSONObject.toJSONString(channelMerchant),JSONObject.toJSONString(channelGroupBooking));

        // 团长id，    // 不使用兜底佣金的拼团不需要重算
        if(null == channelGroupBooking || null == channelGroupBooking.getLeaderId() || channelGroupBooking.getLeaderId() == 0 || null == channelGroupBooking.getUseBaseRebateRate() || 0 == channelGroupBooking.getUseBaseRebateRate() ) {
            log.info("退款时，不需要重算佣金：{}", JSONObject.toJSONString(channelGroupBooking));
            return;
        }
        Integer leaderId = channelGroupBooking.getLeaderId();
        // 团长佣金
        BigDecimal leaderAmount = BigDecimal.ZERO;
        /** 重新计算佣金 */
        recalculateUserCommission(logID, channelMerchant, activityGroupId, null, leaderId);

        // 对以前的订单按照佣金比例优先级重新计算
        // 该活动对应的订单下的活动商品id
        List<StoreOrder> storeOrderList = storeOrderService.list(Wrappers.<StoreOrder>lambdaQuery()
                .eq(StoreOrder::getActivityId, activityGroupId));
        Integer orderId = orderInfo.getOrderId();
        List<Integer> orderIds = storeOrderList.stream().map(StoreOrder::getId).filter(e -> !Objects.equals(e, orderId)).distinct().collect(Collectors.toList());

        List<StoreOrderInfo> orderInfoList = storeOrderInfoService.list(Wrappers.<StoreOrderInfo>lambdaQuery()
                .in(StoreOrderInfo::getOrderId, orderIds));
        log.info("refundCommissionGroupActivity该活动对应的订单下的活动商品id:[{}],{},{}",logID,JSONObject.toJSONString(storeOrderList),JSONObject.toJSONString(orderInfoList));
        for(StoreOrderInfo info : orderInfoList){
            // 获取商品的佣金比例
            StoreProductMer storeProduct = merStoreProductService.getProductMerById(info.getProductId(), storeOrder.getMerId());
            BigDecimal rebateRate  = storeProduct.getRebateRate();
            log.info("refundCommissionGroupActivity获取商品的佣金比例:[{}],{}",logID,rebateRate);
            if(null == rebateRate || rebateRate.compareTo(BigDecimal.ZERO) <= 0){
                // 获取渠道商的佣金比例
                rebateRate = distribution.getBaseRebateRate();
                log.info("refundCommissionGroupActivity获取兜底的佣金比例:[{}],{}",logID,rebateRate);
                if(null == rebateRate || rebateRate.compareTo(BigDecimal.ZERO) <= 0){
                    continue;
                }
            }
            StoreCartResponse storeCartResponse3 = JSON.parseObject(info.getInfo(), StoreCartResponse.class);
            StoreProductAttrValue attrInfo3 = storeCartResponse3.getProductInfo().getAttrInfo();

            // 对以前的商品按照佣金比例优先级重新计算
            BigDecimal price = channelMerchant.getAppletType() == 1 ? attrInfo3.getPaidPrice() : attrInfo3.getProductPaidPrice();
            BigDecimal amount = price.multiply(rebateRate.movePointLeft(2)).setScale(2, RoundingMode.HALF_DOWN);
            leaderAmount = leaderAmount.add(amount);

            log.info("refundCommissionGroupActivity对以前的商品按照佣金比例优先级重新计算:[{}],{}，{}",logID,amount, leaderAmount);
            Integer orderComplete = 0;
            if(null != info.getStatus() && OrderStatusEnum.COMPLETE.getCode() == info.getStatus()){
                orderComplete = 1;
            }
            this.saveUserCommissionV2(leaderId,info.getChildOrderNumber(),
                    CommissionTypeEnum.YJ_佣金.getCode(),CommissionStatusEnum.YJDJ_佣金冻结.getCode(),CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                    amount,amount,null,null,null,
                    "购买商品-团长佣金",null, activityGroupId, 0, orderComplete);
        }

        //用户资金处理
        User userAccount = new User();
        userAccount.setUid(leaderId);
        userAccount.setBrokeragePrice(leaderAmount);
        userAccount.setFrozenPrice(leaderAmount);
        log.info("用户资金处理leaderAmount:[{}],{}", logID,leaderAmount);

        if(BigDecimal.ZERO.compareTo(leaderAmount) != 0) {
            userService.calcMoney(userAccount);
        }
    }

    /**
     * 佣金可解冻账单
     * @return 可解冻账单
     */
    private List<UserCommission> getFrozenUserCommissionsTest(Integer uid, String orderNo) {
        LambdaQueryWrapper<UserCommission> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserCommission::getUid, uid);
        lambdaQueryWrapper.eq(UserCommission::getOrderId, orderNo);
        lambdaQueryWrapper.eq(UserCommission::getType, CommissionTypeEnum.YJ_佣金.getCode());
        return dao.selectList(lambdaQueryWrapper);
    }

    /**
     * 佣金可解冻账单
     * @param storeOrderInfo 子订单
     * @return 可解冻账单
     */
    private List<UserCommission> getFrozenUserCommissions(StoreOrderInfo storeOrderInfo) {
        LambdaQueryWrapper<UserCommission> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserCommission::getOrderId, storeOrderInfo.getChildOrderNumber());
        lambdaQueryWrapper.eq(UserCommission::getType, CommissionTypeEnum.YJ_佣金.getCode());
        lambdaQueryWrapper.eq(UserCommission::getStatus, CommissionStatusEnum.YJDJ_佣金冻结.getCode());
        lambdaQueryWrapper.eq(UserCommission::getIsFreeze, CommissionFreezeEnum.FREEZE_可解冻.getCode());
        return dao.selectList(lambdaQueryWrapper);
    }

    /**
     * 佣金可解冻账单
     * @param storeOrderInfo 子订单
     * @return 可解冻账单
     */
    private List<UserCommission> getFrozenUserCommissionsV2(StoreOrderInfo storeOrderInfo) {
        if (storeOrderInfo.getUid() == null) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<UserCommission> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserCommission::getOrderId, storeOrderInfo.getChildOrderNumber());
//        lambdaQueryWrapper.eq(UserCommission::getType, CommissionTypeEnum.YJ_佣金.getCode());
        lambdaQueryWrapper.eq(UserCommission::getUid, storeOrderInfo.getUid());
        lambdaQueryWrapper.like(UserCommission::getTitle, "购买商品-一级佣金");
        return dao.selectList(lambdaQueryWrapper);
    }

    /**
     * 佣金可解冻账单
     * @param storeOrderInfo 子订单
     * @return 可解冻账单
     */
    private List<UserCommission> getFrozenUserCommissionsGroupActivity(StoreOrderInfo storeOrderInfo, Integer activityGroupId) {
        LambdaQueryWrapper<UserCommission> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserCommission::getOrderId, storeOrderInfo.getChildOrderNumber());
        lambdaQueryWrapper.eq(UserCommission::getType, CommissionTypeEnum.YJ_佣金.getCode());
        lambdaQueryWrapper.eq(UserCommission::getStatus, CommissionStatusEnum.YJDJ_佣金冻结.getCode());
        lambdaQueryWrapper.eq(UserCommission::getIsFreeze, CommissionFreezeEnum.FREEZE_可解冻.getCode());
        lambdaQueryWrapper.eq(UserCommission::getActivityGroupId, activityGroupId);
        return dao.selectList(lambdaQueryWrapper);
    }

    @Override
    public void unfreezeOrder() {
//        //查询创建时间+30天是否超过当前时间  分页处理解冻
//        PageHelper.startPage(1, 20);
//        LambdaQueryWrapper<UserCommission> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//        lambdaQueryWrapper.eq(UserCommission:: getType,CommissionTypeEnum.YJ_佣金.getCode());
//        lambdaQueryWrapper.eq(UserCommission:: getStatus,CommissionStatusEnum.YJDJ_佣金冻结.getCode());
//        lambdaQueryWrapper.eq(UserCommission:: getIsFreeze,CommissionFreezeEnum.FREEZE_可解冻.getCode());
//        lambdaQueryWrapper.orderByAsc(UserCommission::getCreateTime);
//        List<UserCommission> list = dao.selectList(lambdaQueryWrapper);
//        list.stream().forEach(userCommission -> {
//            //计算冻结时间 +30天 比较当前时间
//            String freezeDate = DateUtil.addDay(userCommission.getCreateTime(), 30, Constants.DATE_FORMAT);
//            //String freezeDate = DateUtil.addSecond(userCommission.getCreateTime(), 2, Constants.DATE_FORMAT);
//            logger.info("解冻时间-freezeDate:{},创建时间-creatTime:{}",freezeDate,DateUtil.dateToStr(userCommission.getCreateTime(), Constants.DATE_FORMAT));
//            int time = DateUtil.compareDate(freezeDate,DateUtil.nowDateTimeStr(),Constants.DATE_FORMAT);
//            if(time < 0){
//                userCommission.setStatus(CommissionStatusEnum.YJJD_佣金解冻.getCode());
//                dao.updateById(userCommission);
//            }
//        });
    }

    @Override
    public BigDecimal selectFreezeAmount(Integer uid,Integer status) {
        UserCommissionRequest request = new UserCommissionRequest();
        request.setStatus(status);
        request.setUid(uid);
        request.setIsFreeze(CommissionFreezeEnum.FREEZE_可解冻.getCode());
        request.setType(CommissionTypeEnum.YJ_佣金.getCode());
        BigDecimal amount = dao.selectSumFreezeAmount(request);
        if(null == amount ){
            return BigDecimal.ZERO;
        }
        return amount;
    }

    @Override
    public PageInfo<UserCommission> selectUserCommissionList(UserCommissionRequest request, PageParamRequest pageParamRequest) {
        LambdaQueryWrapper<UserCommission> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserCommission::getUid,userService.getUserIdException());
        lambdaQueryWrapper.orderByDesc(UserCommission::getCreateTime);
        switch (request.getCommissionType()){
            case 1:
                lambdaQueryWrapper.isNotNull(UserCommission::getWithdrawalAmount);
                break;
            case 2:
                lambdaQueryWrapper.isNotNull(UserCommission::getTotalAmount);
                break;
            case 3:
                lambdaQueryWrapper.isNotNull(UserCommission::getFreezeAmount);
                break;
            case 4:
                lambdaQueryWrapper.isNotNull(UserCommission::getCloseAmount);
                break;
            default:
                throw new CrmebException("佣金类型异常");
        }
        Page<UserCommission> userCommissionPage = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        List<UserCommission> list =  dao.selectList(lambdaQueryWrapper);
        List<String> orderIdList = list.stream().filter(e -> e.getType() == 2).map(UserCommission::getOrderId).distinct().collect(Collectors.toList());
        Map<String, UserExtract> map = new HashMap<>();
        if(CollectionUtils.isNotEmpty(orderIdList)){
            List<UserExtract> extractList = userExtractService.list(Wrappers.<UserExtract>lambdaQuery().in(UserExtract::getId, orderIdList));
            map = extractList.stream().collect(Collectors.toMap(e->e.getId().toString(),e->e));
        }
        List<UserCommission> commisionList = new ArrayList<>();
        for (UserCommission commission : list) {
            if(commission.getFreezeAmount() != null && commission.getFreezeAmount().compareTo(BigDecimal.ZERO) == 0){
                continue;
            }
            if(commission.getType() == 2){
                UserExtract userExtract = map.get(commission.getOrderId());
                commission.setOrderId(Objects.nonNull(userExtract) ? userExtract.getSerialNumber() : null);
            }
            commisionList.add(commission);
        }
        return CommonPage.copyPageInfo(userCommissionPage, commisionList);
    }

    private void completeCommissionTest(StoreOrderInfo storeOrderInfo) {
        List<UserCommission> list = getFrozenUserCommissions(storeOrderInfo);
        list.forEach(userCommission -> {
            userCommission.setStatus(CommissionStatusEnum.YJJD_佣金解冻.getCode());
            dao.updateById(userCommission);
            //解冻记录
            // TODO
            this.saveUserCommission(userCommission.getUid(),userCommission.getOrderId(),
                    CommissionTypeEnum.YJ_佣金.getCode(),CommissionStatusEnum.YJJD_佣金解冻.getCode(),CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                    null,userCommission.getFreezeAmount().negate(),userCommission.getFreezeAmount(),null,null,
                    userCommission.getTitle()+"-解冻",null);
            //用户资金操作
            User userAccount = new User();
            userAccount.setUid(userCommission.getUid());
            userAccount.setFrozenPrice(userCommission.getFreezeAmount().negate());
            userAccount.setWithdrawalPrice(userCommission.getFreezeAmount());
            userService.calcMoney(userAccount);
        });
    }

    @Override
    public void completeCommission(StoreOrderInfo storeOrderInfo) {
        String logID = UUID.randomUUID().toString();
        log.info("logID:[{}]", logID);
        log.info("completeCommission:[{}],{}",logID,JSONObject.toJSONString(storeOrderInfo));
        List<UserCommission> list = getFrozenUserCommissions(storeOrderInfo);
        list.forEach(userCommission -> {
            Integer activityGroupId = userCommission.getActivityGroupId();

            boolean flag = true;
            try {
                if(null != activityGroupId && 0 != activityGroupId) {
                    ChannelGroupBooking channelGroupBooking = channelGroupBookingService.getById(activityGroupId);

                    if (null != channelGroupBooking) {
                        Integer leaderId = channelGroupBooking.getLeaderId();
                        BigDecimal rebateRate = channelGroupBooking.getRebateRate();
                        Integer userBaseRebateRate = channelGroupBooking.getUseBaseRebateRate();
                        // userBaseRebateRate == 0 不使用兜底佣金的可以立即解冻
                        flag = userBaseRebateRate == null || userBaseRebateRate == 0 || leaderId == null || leaderId == 0 || rebateRate == null || rebateRate.compareTo(BigDecimal.ZERO) <= 0 || 1 != channelGroupBooking.getActivityTimeType();
                        log.info("completeCommission存在拼团活动，且使用兜底佣金，且拼团活动是限时的，只需要标记以下即可:[{}],{},{}，flag:{}", logID, JSONObject.toJSONString(userCommission), JSONObject.toJSONString(channelGroupBooking), flag);
                    }
                }
            }catch (Exception e){
                log.error("completeCommission时的拼团活动查找错误：{}", e.fillInStackTrace());
            }

            // 这里对 userCommission.getActivityGroupId() 进行校验，如果存在拼团活动id的话，这里先不解冻，等到拼团结束之后再解冻
            if(null == userCommission.getActivityGroupId()
                    || 0 == userCommission.getActivityGroupId()
                    || flag){
                userCommission.setStatus(CommissionStatusEnum.YJJD_佣金解冻.getCode());
                dao.updateById(userCommission);
                //解冻记录
                // TODO
                this.saveUserCommission(userCommission.getUid(),userCommission.getOrderId(),
                        CommissionTypeEnum.YJ_佣金.getCode(),CommissionStatusEnum.YJJD_佣金解冻.getCode(),CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                        null,userCommission.getFreezeAmount().negate(),userCommission.getFreezeAmount(),null,null,
                        userCommission.getTitle()+"-解冻",null);
                //用户资金操作
                User userAccount = new User();
                userAccount.setUid(userCommission.getUid());
                userAccount.setFrozenPrice(userCommission.getFreezeAmount().negate());
                userAccount.setWithdrawalPrice(userCommission.getFreezeAmount());
                userService.calcMoney(userAccount);
            }else{
                // 存在拼团活动，且拼团活动是限时的，只需要标记以下即可，后面有定时任务统一处理
                userCommission.setOrderComplete(SwitchEnum.OPEN.getCode());
                log.info("completeCommission存在拼团活动，且拼团活动是限时的，只需要标记以下即可:[{}],{}",logID,JSONObject.toJSONString(userCommission));
                dao.updateById(userCommission);
            }

        });
    }

    @Override
    public void completeCommissionForGroupActivity() {
        // 获取 没有计算佣金的且佣金比例不为空的 拼团活动
        String logID = UUID.randomUUID().toString();
        log.info("logID:[{}]", logID);
        log.info("completeCommissionForGroupActivity:[{}]",logID);

        List<ChannelGroupBooking> groupBookingList = channelGroupBookingService.list(Wrappers.<ChannelGroupBooking>lambdaQuery()
                .eq(ChannelGroupBooking::getRebateFinish, SwitchEnum.CLOSE.getCode())
                // 使用兜底佣金的才需要在定时任务这里解冻
                .eq(ChannelGroupBooking::getUseBaseRebateRate, SwitchEnum.OPEN.getCode())
                .isNotNull(ChannelGroupBooking::getRebateRate)
        );
        log.info("completeCommissionForGroupActivity groupBookingList:[{}],{}",logID,groupBookingList);

        if(CollectionUtils.isEmpty(groupBookingList)){
            return;
        }
        for(ChannelGroupBooking groupBooking:groupBookingList ){
            // 判断活动是否结束
            Date activityEndTime = groupBooking.getActivityEndTime();
            if(activityEndTime == null || activityEndTime.after(new Date())){
                continue;
            }
            // 归还库存(在这里加个归还库存是为了应对存在未完成订单进行退款的)
            List<Integer> activityIds = channelGroupBookingService.getActivityIds(groupBooking.getMerId());
            storeProductStockService.returnStockForActivityFinish(groupBooking,activityIds, logID);

            if(null == groupBooking.getRebateRate() || groupBooking.getRebateRate().compareTo(BigDecimal.ZERO) <= 0){
                continue;
            }

            Integer leaderId = groupBooking.getLeaderId();
            if(null == leaderId || leaderId == 0) {
                continue;
            }

            List<UserCommission> commissionList = this.list(Wrappers.<UserCommission>lambdaQuery()
                    .eq(UserCommission::getActivityGroupId, groupBooking.getId())
                    .eq(UserCommission::getIsFreeze, CommissionFreezeEnum.FREEZE_可解冻.getCode())
                    .eq(UserCommission::getStatus, CommissionStatusEnum.YJDJ_佣金冻结.getCode())
                    .eq(UserCommission::getType, CommissionTypeEnum.YJ_佣金.getCode()));

            // 校验本次活动下的订单是否存在未完成的订单
            List<UserCommission> filterList = commissionList.stream().filter(e -> e.getOrderComplete() == null || e.getOrderComplete() == 0).collect(Collectors.toList());
            log.info("校验本次活动下的订单是否存在未完成的订单[{}],commissionList :{}，filterList:{}",logID,commissionList, filterList);

            if(!CollectionUtils.isEmpty(filterList)){
                continue;
            }
            for(UserCommission commission : commissionList){
                if(null != commission.getOrderComplete() && SwitchEnum.OPEN.getCode() == commission.getOrderComplete()){
                    commission.setStatus(CommissionStatusEnum.YJJD_佣金解冻.getCode());
                    dao.updateById(commission);
                    //解冻记录
                    // TODO
                    this.saveUserCommission(commission.getUid(),commission.getOrderId(),
                            CommissionTypeEnum.YJ_佣金.getCode(),CommissionStatusEnum.YJJD_佣金解冻.getCode(),CommissionFreezeEnum.FREEZE_可解冻.getCode(),
                            null,commission.getFreezeAmount().negate(),commission.getFreezeAmount(),null,null,
                            commission.getTitle()+"-解冻",null);
                    //用户资金操作
                    log.info("用户资金操作:[{}],{}",logID,JSONObject.toJSONString(commission));
                    User userAccount = new User();
                    userAccount.setUid(commission.getUid());
                    userAccount.setFrozenPrice(commission.getFreezeAmount().negate());
                    userAccount.setWithdrawalPrice(commission.getFreezeAmount());
                    userService.calcMoney(userAccount);
                }
            }
            // 设置此次活动已结束佣金计算
            groupBooking.setRebateFinish(SwitchEnum.OPEN.getCode());
            channelGroupBookingService.updateById(groupBooking);
        }
//        List<ChannelGroupBooking> bookingList = channelGroupBookingService.list(Wrappers.<ChannelGroupBooking>lambdaQuery()
//                .eq(ChannelGroupBooking::getReturnStock, SwitchEnum.CLOSE.getCode())
//        );
//        log.info("completeCommissionForGroupActivity groupBookingList:[{}],{}",logID,groupBookingList);
//
//        for(ChannelGroupBooking booking:bookingList ){
//            // 判断活动是否结束
//            Date activityEndTime = booking.getActivityEndTime();
//            if(activityEndTime == null || activityEndTime.after(new Date())){
//                continue;
//            }
//            // 归还库存
//            List<Integer> activityIds = channelGroupBookingService.getActivityIds(booking.getMerId());
//            storeProductStockService.returnStockForActivityFinish(booking,activityIds, logID);
//
//        }

    }

    @Override
    public void saveUserCommission(Integer uid, String orderId,
                                   Integer type, Integer status, Integer isFreeze,
                                   BigDecimal totalAmount, BigDecimal freezeAmount, BigDecimal withdrawalAmount, BigDecimal closeAmount, BigDecimal userAmount,
                                   String title, String remark) {
        UserCommission userCommission = new UserCommission();
        userCommission.setUid(uid);
        userCommission.setOrderId(orderId);
        userCommission.setTitle(title);
        userCommission.setType(type);
        userCommission.setStatus(status);
        userCommission.setIsFreeze(isFreeze);
        userCommission.setTotalAmount(totalAmount);
        userCommission.setFreezeAmount(freezeAmount);
        userCommission.setWithdrawalAmount(withdrawalAmount);
        userCommission.setCloseAmount(closeAmount);
        userCommission.setUserAmount(userAmount);
        userCommission.setRemark(remark);
        dao.insert(userCommission);
        log.info("新增佣金流水, 用户: {}, JSON: {}", uid, JSONObject.toJSONString(userCommission));
    }

    @Override
    public void saveUserCommissionV2(Integer uid, String orderId,
                                   Integer type, Integer status, Integer isFreeze,
                                   BigDecimal totalAmount, BigDecimal freezeAmount, BigDecimal withdrawalAmount, BigDecimal closeAmount, BigDecimal userAmount,
                                   String title, String remark, Integer activityGroupId, Integer isGroupRebate, Integer orderComplete) {
        UserCommission userCommission = new UserCommission();
        userCommission.setUid(uid);
        userCommission.setOrderId(orderId);
        userCommission.setTitle(title);
        userCommission.setType(type);
        userCommission.setStatus(status);
        userCommission.setIsFreeze(isFreeze);
        userCommission.setTotalAmount(totalAmount);
        userCommission.setFreezeAmount(freezeAmount);
        userCommission.setWithdrawalAmount(withdrawalAmount);
        userCommission.setCloseAmount(closeAmount);
        userCommission.setUserAmount(userAmount);
        userCommission.setRemark(remark);
        userCommission.setActivityGroupId(activityGroupId);
        userCommission.setIsGroupRebate(isGroupRebate);
        userCommission.setOrderComplete(orderComplete);
        dao.insert(userCommission);
        log.info("新增佣金流水, 用户: {}, JSON: {}", uid, JSONObject.toJSONString(userCommission));
    }

    @Override
    public PageInfo<RetailShopUserOrderResponse> getOrderListBySpreadLevel(RetailShopStairUserRequest request, PageParamRequest pageParamRequest) {
        PageHelper.startPage(pageParamRequest.getPage(),pageParamRequest.getLimit());
        List<RetailShopUserOrderResponse> orderResponseList = dao.getOrderListBySpreadLevel(request);
        return new PageInfo<>(orderResponseList);
    }

    /**
     * 查询分销头部信息
     * @param uidList
     * @return com.zbkj.crmeb.store.response.RetailShopTopResponse
     */
    @Override
    public RetailShopTopResponse getPromotionOrder(List<Integer> uidList) {
        RetailShopTopResponse response = new RetailShopTopResponse();
        List<UserCommission> userCommissions = dao.selectList(new LambdaQueryWrapper<>(UserCommission.class).eq(UserCommission::getType, CommissionTypeEnum.YJ_佣金.getCode()).in(UserCommission::getUid,uidList).ge(UserCommission::getFreezeAmount, BigDecimal.ZERO).groupBy(UserCommission::getOrderId));
        if (CollectionUtils.isNotEmpty(userCommissions)){
            List<String> strings = userCommissions.stream().map(UserCommission::getOrderId).collect(Collectors.toList());
            response.setPromotionOrders(userCommissions.size());
            response.setOrderPaidAmount(orderInfoService.getOrderPaidAmount(strings));
        }
        return response;
    }

}


